<?php

namespace apiend\modules\mall\models;

use Yii;
use common\helpers\ArrayHelper;
use common\models\shop\ShopProduct;
use common\models\shop\ShopGoods;
use common\models\shop\ShopCart;
use common\logics\DiscountLogic;
use common\logics\address\FrontUserAddressLogic;
use yii\db\Expression;
use common\logics\ExpressCalculator;
use common\models\user\UserCoupon;

/**
 * 购物车结算准备处理模型
 * 
 * @author emhome<emhome@163.com>
 * @since 2.0
 */
class CartPackBalanceForm extends \common\base\Model {

    /**
     * @var integer 下单用户ID
     */
    public $user_id;

    /**
     * @var array 结算内容单元
     */
    public $ids;

    /**
     * @var array 待结算SKU
     */
    private $_carts = [];

    /**
     * @inheritdoc
     */
    public function rules() {
        return [
            [['ids'], 'required'],
            [['ids'], 'string'],
            [['user_id'], 'integer'],
            [['ids'], 'validateItems'],
        ];
    }

    /**
     * 校验提交商品的信息
     * @param string $attribute the attribute currently being validated
     */
    public function validateItems($attribute) {
        if ($this->hasErrors()) {
            return;
        }
        $items = array_unique(explode(',', $this->$attribute));
        if (empty($items)) {
            return $this->addError($attribute, '请选择要进行结算的商品');
        }
        $carts = $this->loadCartItems($items);
        if (empty($carts)) {
            return $this->addError($attribute, '准备结算的商品已下架或者库存不足，请更新购物车后重新提交');
        } else {
            $cartIds = ArrayHelper::getColumn($carts, 'id');
            if (!empty(array_diff($items, $cartIds))) {
                return $this->addError($attribute, '准备结算的商品已下架或者库存不足，请更新购物车后重新提交');
            }
        }
        $this->_carts = $carts;
    }

    /**
     * 获取待结算内容
     * @return boolean
     */
    public function loadCartItems($ids) {
        $query = CartSearch::findActive('t')->andWhere([
            't.user_id' => $this->user_id,
            't.id' => $ids,
        ])
        ->innerJoinWith([
            'product p' => function ($q) {
                $q->active(ShopProduct::STATUS_ACTIVE);
            },
            'goods g' => function ($q) {
                $q->active(ShopGoods::STATUS_ACTIVE);
            },
        ]);
        $expression = new Expression('`g`.`stock`  + `g`.`shelf` - `g`.`total`');
        $query->andWhere(['<=', 't.num', $expression]);

        return $query->all();
    }

    public function getWaitBalance() {
        return $this->_carts;
    }

    /**
     * 结算准备处理
     * @return array
     */
    public function save() {
        if (!$this->validate()) {
            return $this->dumpError('购物车结算准备失败');
        }


        $expressPrice = 0;

        //待结算购物车列表
        $list = $this->getWaitBalance();

        //更新购物车中条目的结算状态
        $this->prepareUpdateCartItemStatus($list);

        //收件地址
        $addressList = FrontUserAddressLogic::findByUserId($this->user_id);
        if (!empty($addressList)) {
            $expressPrice = $this->reckonExpress($list, $addressList[0]);
        }

        //计算折扣
        $order = $this->reckonPrice($list, $expressPrice);

        $items = CartSearch::groupFormat($list);
        return [
            'address' => $addressList,
            'items' => array_values($items),
            'order' => $order,
        ];
    }

    /**
     * 更新购物车中条目的结算状态
     * @param array $list
     * @throws ModelHttpException
     * @return boolean
     */
    public function prepareUpdateCartItemStatus($list) {
        $transaction = Yii::$app->db->beginTransaction();
        try {
            ShopCart::updateAll(['status' => ShopCart::STATUS_DEFAULT], [
                'user_id' => $this->user_id
            ]);
            ShopCart::updateAll(['status' => ShopCart::STATUS_PREPARE_ORDER], [
                'id' => ArrayHelper::getColumn($list, 'id')
            ]);
            $transaction->commit();
        } catch (Exception $e) {
            $transaction->rollBack();
            return $this->dumpError($e->getMessage(), false);
        }
        return true;
    }

    /**
     * 邮费计算
     * @param array $list
     * @param FrontUserAddressLogic $address
     * @return float
     */
    public function reckonExpress($list, $address) {
        $expressItems = [];
        foreach ($list as $cart) {
            $expressItems[] = [
                'product_id' => $cart->product_id,
                'num' => $cart->num,
            ];
        }
        $calcexpress = new ExpressCalculator();
        $calcexpress->setAttributes([
            'items' => $expressItems,
            'areacode' => $address->area_code,
        ]);
        return $calcexpress->reckon();
    }

    /**
     * 计算结算金额信息
     * @param array $list
     * @param integer $express
     * @return float
     */
    public function reckonPrice($list, $express = 0) {
        if (empty($list)) {
            return;
        }
        $amount = 0;
        $discount = 0;
        $dislogic = new DiscountLogic($list);
        $goods = $dislogic->reckon();
        foreach ($goods as $ginfo) {
            $_amount = $ginfo['price'] * $ginfo['number'];
            $_discount = $_amount - $ginfo['subtotal'];
            $amount += $_amount;
            $discount += $_discount;
        }
        //折扣券
        $coupons = UserCoupon::findDiscountValue($this->user_id);
        if (!empty($coupons)) {
            $discount += array_sum($coupons) / 100;
        }

        $subtotal = $amount - $discount + $express;
        $payment = $subtotal;

        $data = compact('amount', 'discount', 'express', 'subtotal', 'payment');
        return array_map(function($value) {
            return number_format($value, 2, '.', '');
        }, $data);
    }

}
